/**
 * 手机号工具类
 * 提供手机号校验、格式化等常用方法
 */

/**
 * 手机号校验结果接口
 */
export interface PhoneValidationResult {
  isValid: boolean;
  message: string;
  country?: string;
}

/**
 * 国家手机号规则配置
 */
interface CountryPhoneRule {
  name: string;
  code: string;
  pattern: RegExp;
  length: number[];
  example: string;
}

/**
 * 支持的国家手机号规则
 */
const COUNTRY_PHONE_RULES: Record<string, CountryPhoneRule> = {
  CN: {
    name: '中国',
    code: '+86',
    pattern: /^1[3-9]\d{9}$/,
    length: [11],
    example: '13800138000'
  },
  US: {
    name: '美国',
    code: '+1',
    pattern: /^[2-9]\d{2}[2-9]\d{2}\d{4}$/,
    length: [10],
    example: '2025551234'
  },
  UK: {
    name: '英国',
    code: '+44',
    pattern: /^[1-9]\d{8,9}$/,
    length: [9, 10],
    example: '7700123456'
  },
  JP: {
    name: '日本',
    code: '+81',
    pattern: /^[789]0\d{8}$/,
    length: [11],
    example: '9012345678'
  },
  KR: {
    name: '韩国',
    code: '+82',
    pattern: /^1[0-9]\d{7,8}$/,
    length: [9, 10],
    example: '1012345678'
  },
  DE: {
    name: '德国',
    code: '+49',
    pattern: /^1[5-7]\d{8,9}$/,
    length: [10, 11],
    example: '15123456789'
  },
  FR: {
    name: '法国',
    code: '+33',
    pattern: /^[67]\d{8}$/,
    length: [9],
    example: '612345678'
  },
  AU: {
    name: '澳大利亚',
    code: '+61',
    pattern: /^4\d{8}$/,
    length: [9],
    example: '412345678'
  }
};

/**
 * 基础手机号校验
 * @param phone 手机号
 * @returns 校验结果
 */
export function validatePhone(phone: string): PhoneValidationResult {
  if (!phone) {
    return {
      isValid: false,
      message: '手机号不能为空'
    };
  }

  // 移除所有非数字字符（除了+号）
  const cleanPhone = phone.replace(/[^\d+]/g, '');
  
  if (cleanPhone.length < 7) {
    return {
      isValid: false,
      message: '手机号长度过短'
    };
  }

  if (cleanPhone.length > 15) {
    return {
      isValid: false,
      message: '手机号长度过长'
    };
  }

  return {
    isValid: true,
    message: '手机号格式正确'
  };
}

/**
 * 检查手机号是否为空
 * @param phone 手机号
 * @returns 是否为空
 */
export function isPhoneEmpty(phone: string | null | undefined): boolean {
  return !phone || phone.trim() === '';
}

/**
 * 校验带+号的国际手机号
 * @param phone 手机号
 * @returns 校验结果
 */
export function validateInternationalPhone(phone: string): PhoneValidationResult {
  if (isPhoneEmpty(phone)) {
    return {
      isValid: false,
      message: '手机号不能为空'
    };
  }

  // 检查是否以+号开头
  if (!phone.startsWith('+')) {
    return {
      isValid: false,
      message: '国际手机号必须以+号开头'
    };
  }

  // 移除+号，获取国家代码和号码
  const withoutPlus = phone.substring(1);
  
  // 查找匹配的国家规则
  for (const [countryCode, rule] of Object.entries(COUNTRY_PHONE_RULES)) {
    if (withoutPlus.startsWith(rule.code.substring(1))) {
      const localNumber = withoutPlus.substring(rule.code.length - 1);
      
      if (rule.pattern.test(localNumber) && rule.length.includes(localNumber.length)) {
        return {
          isValid: true,
          message: `${rule.name}手机号格式正确`,
          country: countryCode
        };
      }
    }
  }

  return {
    isValid: false,
    message: '不支持的手机号格式或国家代码'
  };
}

/**
 * 校验指定国家的手机号
 * @param phone 手机号
 * @param countryCode 国家代码 (如: CN, US, UK)
 * @returns 校验结果
 */
export function validateCountryPhone(phone: string, countryCode: string): PhoneValidationResult {
  if (isPhoneEmpty(phone)) {
    return {
      isValid: false,
      message: '手机号不能为空'
    };
  }

  const rule = COUNTRY_PHONE_RULES[countryCode.toUpperCase()];
  if (!rule) {
    return {
      isValid: false,
      message: `不支持的国家代码: ${countryCode}`
    };
  }

  // 移除所有非数字字符
  const cleanPhone = phone.replace(/\D/g, '');
  
  if (!rule.pattern.test(cleanPhone)) {
    return {
      isValid: false,
      message: `${rule.name}手机号格式不正确，示例: ${rule.example}`
    };
  }

  if (!rule.length.includes(cleanPhone.length)) {
    return {
      isValid: false,
      message: `${rule.name}手机号长度不正确，应为${rule.length.join('或')}位`
    };
  }

  return {
    isValid: true,
    message: `${rule.name}手机号格式正确`,
    country: countryCode.toUpperCase()
  };
}

/**
 * 格式化手机号（添加+号）
 * @param phone 手机号
 * @param countryCode 国家代码
 * @returns 格式化后的手机号
 */
export function formatPhoneWithCountryCode(phone: string, countryCode: string): string {
  if (isPhoneEmpty(phone)) {
    return '';
  }

  const rule = COUNTRY_PHONE_RULES[countryCode.toUpperCase()];
  if (!rule) {
    return phone;
  }

  // 移除所有非数字字符
  const cleanPhone = phone.replace(/\D/g, '');
  
  // 如果已经包含国家代码，直接返回
  if (phone.startsWith('+')) {
    return phone;
  }

  return `+${rule.code.substring(1)}${cleanPhone}`;
}

/**
 * 格式化手机号显示（添加分隔符）
 * @param phone 手机号
 * @param countryCode 国家代码
 * @returns 格式化后的手机号
 */
export function formatPhoneDisplay(phone: string, countryCode: string = 'CN'): string {
  if (isPhoneEmpty(phone)) {
    return '';
  }

  const rule = COUNTRY_PHONE_RULES[countryCode.toUpperCase()];
  if (!rule) {
    return phone;
  }

  // 移除所有非数字字符
  const cleanPhone = phone.replace(/\D/g, '');
  
  // 中国手机号格式化
  if (countryCode.toUpperCase() === 'CN' && cleanPhone.length === 11) {
    return `${cleanPhone.slice(0, 3)}-${cleanPhone.slice(3, 7)}-${cleanPhone.slice(7)}`;
  }

  // 美国手机号格式化
  if (countryCode.toUpperCase() === 'US' && cleanPhone.length === 10) {
    return `(${cleanPhone.slice(0, 3)}) ${cleanPhone.slice(3, 6)}-${cleanPhone.slice(6)}`;
  }

  // 默认格式化（每3位添加一个空格）
  return cleanPhone.replace(/(\d{3})(?=\d)/g, '$1 ');
}

/**
 * 获取支持的国家列表
 * @returns 支持的国家列表
 */
export function getSupportedCountries(): Array<{code: string, name: string, example: string}> {
  return Object.entries(COUNTRY_PHONE_RULES).map(([code, rule]) => ({
    code,
    name: rule.name,
    example: rule.example
  }));
}

/**
 * 从手机号中提取国家代码
 * @param phone 手机号
 * @returns 国家代码或null
 */
export function extractCountryCode(phone: string): string | null {
  if (isPhoneEmpty(phone) || !phone.startsWith('+')) {
    return null;
  }

  const withoutPlus = phone.substring(1);
  
  for (const [countryCode, rule] of Object.entries(COUNTRY_PHONE_RULES)) {
    if (withoutPlus.startsWith(rule.code.substring(1))) {
      return countryCode;
    }
  }

  return null;
}

/**
 * 手机号脱敏处理
 * @param phone 手机号
 * @param maskChar 掩码字符，默认为*
 * @returns 脱敏后的手机号
 */
export function maskPhone(phone: string, maskChar: string = '*'): string {
  if (isPhoneEmpty(phone)) {
    return '';
  }

  const cleanPhone = phone.replace(/\D/g, '');
  
  if (cleanPhone.length < 4) {
    return phone;
  }

  if (cleanPhone.length <= 7) {
    return `${cleanPhone.slice(0, 2)}${maskChar.repeat(cleanPhone.length - 4)}${cleanPhone.slice(-2)}`;
  }

  return `${cleanPhone.slice(0, 3)}${maskChar.repeat(cleanPhone.length - 6)}${cleanPhone.slice(-3)}`;
}

/**
 * 批量手机号校验结果接口
 */
export interface BatchPhoneValidationResult {
  isValid: boolean;
  message: string;
  validPhones: string[];
  invalidPhones: Array<{
    phone: string;
    reason: string;
  }>;
  duplicatePhones: string[];
  totalCount: number;
  validCount: number;
  invalidCount: number;
  duplicateCount: number;
  emptyCount: number;
  exceededCount: number;
}

/**
 * 批量手机号校验配置
 */
export interface BatchPhoneValidationConfig {
  maxCount?: number;           // 最大数量限制
  minCount?: number;           // 最小数量限制
  checkUnique?: boolean;        // 是否检查唯一性
  countryCode?: string;         // 国家代码
  allowEmpty?: boolean;         // 是否允许空值
  strictMode?: boolean;         // 严格模式（所有号码必须有效）
}

/**
 * 批量手机号校验
 * @param phones 手机号数组
 * @param config 校验配置
 * @returns 批量校验结果
 */
export function validateBatchPhones(
  phones: string[], 
  config: BatchPhoneValidationConfig = {}
): BatchPhoneValidationResult {
  const {
    maxCount = 1000,           // 默认最大1000个
    minCount = 1,              // 默认最少1个
    checkUnique = true,        // 默认检查唯一性
    countryCode = 'CN',        // 默认中国
    allowEmpty = false,        // 默认不允许空值
    strictMode = false         // 默认非严格模式
  } = config;

  const result: BatchPhoneValidationResult = {
    isValid: true,
    message: '批量校验完成',
    validPhones: [],
    invalidPhones: [],
    duplicatePhones: [],
    totalCount: phones ? phones.length : 0,
    validCount: 0,
    invalidCount: 0,
    duplicateCount: 0,
    emptyCount: 0,
    exceededCount: 0
  };

  // 检查输入是否为空
  if (!phones || phones.length === 0) {
    return {
      ...result,
      isValid: false,
      message: '手机号列表不能为空'
    };
  }

  // 检查数量限制
  if (phones.length > maxCount) {
    return {
      ...result,
      isValid: false,
      message: `手机号数量超过限制，最多允许 ${maxCount} 个，当前 ${phones.length} 个`,
      exceededCount: phones.length - maxCount
    };
  }

  if (phones.length < minCount) {
    return {
      ...result,
      isValid: false,
      message: `手机号数量不足，至少需要 ${minCount} 个，当前 ${phones.length} 个`
    };
  }

  // 用于检查重复的手机号
  const phoneSet = new Set<string>();
  const duplicateSet = new Set<string>();

  // 逐个校验手机号
  for (const phone of phones) {
    // 检查是否为空
    if (isPhoneEmpty(phone)) {
      if (allowEmpty) {
        result.emptyCount++;
        continue;
      } else {
        result.invalidPhones.push({
          phone,
          reason: '手机号不能为空'
        });
        result.invalidCount++;
        continue;
      }
    }

    // 检查唯一性
    if (checkUnique) {
      const normalizedPhone = phone.replace(/\D/g, '');
      if (phoneSet.has(normalizedPhone)) {
        duplicateSet.add(normalizedPhone);
        result.duplicatePhones.push(phone);
        result.duplicateCount++;
        continue;
      }
      phoneSet.add(normalizedPhone);
    }

    // 校验手机号格式
    const validation = validateCountryPhone(phone, countryCode);
    if (validation.isValid) {
      result.validPhones.push(phone);
      result.validCount++;
    } else {
      result.invalidPhones.push({
        phone,
        reason: validation.message
      });
      result.invalidCount++;
    }
  }

  // 处理重复的手机号
  if (checkUnique && duplicateSet.size > 0) {
    result.duplicatePhones = Array.from(duplicateSet);
    result.duplicateCount = duplicateSet.size;
  }

  // 严格模式：所有号码必须有效
  if (strictMode && result.invalidCount > 0) {
    result.isValid = false;
    result.message = `严格模式：发现 ${result.invalidCount} 个无效号码，所有号码必须有效`;
  } else if (result.invalidCount > 0 || result.duplicateCount > 0) {
    result.isValid = false;
    result.message = `校验完成，发现 ${result.invalidCount} 个无效号码，${result.duplicateCount} 个重复号码`;
  } else {
    result.message = `校验完成，所有 ${result.validCount} 个手机号都有效`;
  }

  return result;
}

/**
 * 批量手机号校验（简化版本，保持向后兼容）
 * @param phones 手机号数组
 * @param countryCode 国家代码，默认为CN
 * @param checkUnique 是否检查唯一性，默认为true
 * @returns 批量校验结果
 */
export function validateBatchPhonesSimple(
  phones: string[], 
  countryCode: string = 'CN',
  checkUnique: boolean = true
): BatchPhoneValidationResult {
  return validateBatchPhones(phones, {
    countryCode,
    checkUnique,
    maxCount: 1000,
    minCount: 1,
    allowEmpty: false,
    strictMode: false
  });
}

/**
 * 批量手机号格式化
 * @param phones 手机号数组
 * @param countryCode 国家代码
 * @returns 格式化后的手机号数组
 */
export function formatBatchPhones(phones: string[], countryCode: string = 'CN'): string[] {
  return phones
    .filter(phone => !isPhoneEmpty(phone))
    .map(phone => formatPhoneWithCountryCode(phone, countryCode));
}

/**
 * 批量手机号脱敏处理
 * @param phones 手机号数组
 * @param maskChar 掩码字符，默认为*
 * @returns 脱敏后的手机号数组
 */
export function maskBatchPhones(phones: string[], maskChar: string = '*'): string[] {
  return phones
    .filter(phone => !isPhoneEmpty(phone))
    .map(phone => maskPhone(phone, maskChar));
}

/**
 * 检查手机号数量限制
 * @param phones 手机号数组
 * @param maxCount 最大数量
 * @param minCount 最小数量
 * @returns 检查结果
 */
export function checkPhoneCountLimit(
  phones: string[], 
  maxCount: number = 1000, 
  minCount: number = 1
): { isValid: boolean; message: string; exceededCount?: number } {
  if (!phones || phones.length === 0) {
    return {
      isValid: false,
      message: '手机号列表不能为空'
    };
  }

  if (phones.length > maxCount) {
    return {
      isValid: false,
      message: `手机号数量超过限制，最多允许 ${maxCount} 个，当前 ${phones.length} 个`,
      exceededCount: phones.length - maxCount
    };
  }

  if (phones.length < minCount) {
    return {
      isValid: false,
      message: `手机号数量不足，至少需要 ${minCount} 个，当前 ${phones.length} 个`
    };
  }

  return {
    isValid: true,
    message: `手机号数量符合要求，当前 ${phones.length} 个`
  };
}

/**
 * 分页处理手机号数组
 * @param phones 手机号数组
 * @param pageSize 每页大小
 * @param page 页码（从1开始）
 * @returns 分页结果
 */
export function paginatePhones(
  phones: string[], 
  pageSize: number = 100, 
  page: number = 1
): { 
  data: string[]; 
  total: number; 
  page: number; 
  pageSize: number; 
  totalPages: number;
  hasNext: boolean;
  hasPrev: boolean;
} {
  const total = phones.length;
  const totalPages = Math.ceil(total / pageSize);
  const startIndex = (page - 1) * pageSize;
  const endIndex = startIndex + pageSize;
  
  return {
    data: phones.slice(startIndex, endIndex),
    total,
    page,
    pageSize,
    totalPages,
    hasNext: page < totalPages,
    hasPrev: page > 1
  };
}

/**
 * 从手机号数组中提取唯一号码
 * @param phones 手机号数组
 * @returns 去重后的手机号数组
 */
export function getUniquePhones(phones: string[]): string[] {
  const phoneSet = new Set<string>();
  const uniquePhones: string[] = [];

  for (const phone of phones) {
    if (isPhoneEmpty(phone)) continue;
    
    const normalizedPhone = phone.replace(/\D/g, '');
    if (!phoneSet.has(normalizedPhone)) {
      phoneSet.add(normalizedPhone);
      uniquePhones.push(phone);
    }
  }

  return uniquePhones;
}

/**
 * 批量手机号分类
 * @param phones 手机号数组
 * @param countryCode 国家代码
 * @returns 分类结果
 */
export function categorizeBatchPhones(phones: string[], countryCode: string = 'CN') {
  const result = {
    valid: [] as string[],
    invalid: [] as Array<{ phone: string; reason: string }>,
    duplicates: [] as string[],
    empty: [] as string[]
  };

  const phoneSet = new Set<string>();
  const duplicateSet = new Set<string>();

  for (const phone of phones) {
    // 空值检查
    if (isPhoneEmpty(phone)) {
      result.empty.push(phone);
      continue;
    }

    // 重复检查
    const normalizedPhone = phone.replace(/\D/g, '');
    if (phoneSet.has(normalizedPhone)) {
      duplicateSet.add(normalizedPhone);
      result.duplicates.push(phone);
      continue;
    }
    phoneSet.add(normalizedPhone);

    // 格式校验
    const validation = validateCountryPhone(phone, countryCode);
    if (validation.isValid) {
      result.valid.push(phone);
    } else {
      result.invalid.push({
        phone,
        reason: validation.message
      });
    }
  }

  return result;
}
